package dse;

import java.lang.reflect.Constructor;
import java.util.Map;
import java.util.Properties;

import dse.modules.Module;

public class ModuleLoader {
	private ExperimentConfiguration sysSettings;
	private Properties props;
	
	
	public ModuleLoader (ExperimentConfiguration settings, Properties props) {
		this.sysSettings = settings;
		this.props = props;
	}
	
	
	@SuppressWarnings({ "unchecked", "rawtypes"})
	public Module loadModule (
			String name, 
			Class requiredInterface
			)
	throws DseException
	{
		try {
			String prefix = "module." + name;
			String className = props.getProperty(prefix);
			if (className == null)
				throw new ClassNotFoundException(
						"No classname given in properties file for module."
						);
			
			Class<Module> mc = (Class<Module>)(Class.forName(className));
			if (requiredInterface.isAssignableFrom(mc) == false)
				throw new DseException (
						"Class " + mc.getName() + " is not an instance of " + 
						requiredInterface.getName()
						);
	
			Constructor c = mc.getConstructor(new Class [0]);
			Module m = (Module)c.newInstance(new Object [0]);
			
			Map<String, String> modulesSettings = 
				PropertiesUtil.collectSubset(props, prefix + ".");
			
			m.initalize(sysSettings, modulesSettings);
			
			return m;
		} catch (Exception e) {
			throw new DseException (
					"Couldn't load module '" + name + "'.", 
					e
					);
		}
	}

	@SuppressWarnings({"rawtypes" })
	public Module loadOptionalModule (
			String name, 
			Class requiredInterface
			)
	throws DseException
	{
		String prefix = "module." + name;
		String className = props.getProperty(prefix);
		if (className == null)
			return null;
		return loadModule(name,requiredInterface);
	}
}
